package pl.enigmatic.math.graph;

import java.util.List;

import pl.enigmatic.HasName;


public class AttachedSingleParentedLeafTree<L extends AttachedSingleParentedLeaf<?, L, T>, B extends HasName, T extends AttachedSingleParentedLeafTree<L, B, T>>
		extends AttachedLeafsTree<L, B, T> {

	public static <L extends AttachedSingleParentedLeaf<?, L, T>, T extends AttachedSingleParentedLeafTree<L, ?, T>> int setParentChildRelationship(
			final T parent, final L leaf, int index) {
		if (leaf != null && (parent != null || parent != leaf.parent)) {// coś do zmiany mamy - dziecko istnieje i jeden z rodziców też
			final T oldParent = leaf.parent;
			if (parent == null) {
				index = -1;
				if (oldParent.removeAttachedLeafSuper(leaf)) {
					leaf.parent = null;
					leaf.onParentChanged(oldParent);
				}
			} else {
				leaf.parent = parent;
				if (oldParent != null) {
					oldParent.removeAttachedLeafSuper(leaf);
				}
				final boolean changed = oldParent != parent || !parent.containsAttachedLeaf(leaf);
				index = parent.addAttachedLeafSuper(leaf, index);
				if (changed) {
					leaf.onParentChanged(oldParent);
				}
			}
			return index;
		}
		return -1;
	}

	public AttachedSingleParentedLeafTree(final B base, final List<B> baseChildren, final List<L> leafs) {
		super(base, baseChildren, leafs);
	}

	public AttachedSingleParentedLeafTree(final B base, final List<B> baseChildren) {
		super(base, baseChildren);
	}

	public AttachedSingleParentedLeafTree(final B base) {
		super(base);
	}

	public int addAttachedLeafSuper(final L attachedLeaf, final int index) {
		return super.addAttachedLeaf(attachedLeaf, index);
	}

	@SuppressWarnings("unchecked")
	@Override
	public int addAttachedLeaf(final L attachedLeaf, final int index) {
		return setParentChildRelationship((T) this, attachedLeaf, index);
	}

	public boolean removeAttachedLeafSuper(final L attachedLeaf) {
		return super.removeAttachedLeaf(attachedLeaf);
	}

	@Override
	public boolean removeAttachedLeaf(final L attachedLeaf) {
		final boolean res = containsAttachedLeaf(attachedLeaf);
		if (res) {
			setParentChildRelationship(null, attachedLeaf, -1);
		}
		return res;
	}

}
